package com.chenfan.process.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chenfan.ccp.common.result.R;
import com.chenfan.notify.vo.NotifyVo;
import com.chenfan.privilege.dto.UserDTO;
import com.chenfan.process.biz.ApprovalBizService;
import com.chenfan.process.biz.ProcessBizQuery;
import com.chenfan.process.biz.ProcessBizService;
import com.chenfan.process.biz.ProcessDetailBizService;
import com.chenfan.process.biz.impl.EventPublisherBiz;
import com.chenfan.process.biz.impl.NotifyBiz;
import com.chenfan.process.dto.ApprovalDTO;
import com.chenfan.process.dto.ApprovalMapDTO;
import com.chenfan.process.dto.ApprovalRejectedDTO;
import com.chenfan.process.dto.ApprovalStatusDTO;
import com.chenfan.process.entity.dto.ApprovalQueryDTO;
import com.chenfan.process.entity.dto.ApprovalTemplateMapDTO;
import com.chenfan.process.entity.dto.ApprovalTransferNodeDTO;
import com.chenfan.process.entity.po.ApprovalPo;
import com.chenfan.process.entity.po.ApprovalTemplatePo;
import com.chenfan.process.entity.vo.ApprovalPersonVo;
import com.chenfan.process.entity.vo.ProcessDetailActiveVO;
import com.chenfan.process.entity.vo.StartApprovalVO;
import com.chenfan.process.service.ApprovalTemplateService;
import com.chenfan.process.vo.ApprovalVo;
import com.chenfan.process.vo.EntireProcessDetailVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * 审批操作
 * 
 * @author K
 * @date 2021/1/25
 */
@Api(tags = "审批流")
@RestController
@RequestMapping("/approval")
public class ApprovalController {

    @Autowired
    private ProcessBizService processBizService;
    @Autowired
    private ProcessDetailBizService processDetailBizService;
    @Autowired
    private ApprovalBizService approvalService;
    @Autowired
    private ProcessBizQuery processBizQuery;
    @Autowired
    private NotifyBiz notifyBiz;
    @Autowired
    private ApprovalTemplateService approvalTemplateService;
    @Autowired
    private EventPublisherBiz eventPublisherBiz;

    /**
     * 开始批准
     * @param approvalTemplateCode 审批模板Code
     * @param approval 发起审批参数
     * @return {@link R}<{@link String}>
     */
    @ApiOperation("发起审批")
    @PostMapping("{approvalTemplateCode}")
    public R<String> startApproval(@RequestHeader(value = "projectName", required = false) String projectName,
        @PathVariable String approvalTemplateCode, @RequestBody ApprovalDTO approval) {
        if (StringUtils.isEmpty(projectName)) {
            projectName = approval.getProjectName();
        }
        StartApprovalVO startApprovalVO = processBizService.startApproval(projectName, approvalTemplateCode, approval);

        // trigger event.
        eventPublisherBiz.triggerEvent();
        eventPublisherBiz.triggerNotify(startApprovalVO.getApprovalPo());
        return R.data(startApprovalVO.getApprovalPo().getApprovalId().toString());
    }

    /**
     * 根据审批ID查询详情
     * @param approvalId 审批ID
     * @return {@link R}<{@link ApprovalVo}>
     */
    @ApiOperation("根据审批ID查询详情")
    @GetMapping("{approvalId}")
    public R<ApprovalVo> getApproval(@PathVariable Long approvalId) {
        return R.data(approvalService.findApprovalByApprovalId(approvalId));
    }

    /**
     * 审批状态变更 审批拒绝
     * @param approvalId 审批id
     * @param approval 审批参数
     * @return {@link R}<{@link Long}>
     */
    @ApiOperation("审批状态变更")
    @PostMapping("/{approvalId}/approval-change")
    public R<Long> approvalChange(@PathVariable Long approvalId, @RequestBody ApprovalDTO approval) throws UnsupportedEncodingException {
        ApprovalPo approvalPo = processBizService.calculateNextOne(approvalId, approval.getUseId(), approval);
        Long data = approvalPo.getApprovalId();
        // trigger event.
        eventPublisherBiz.triggerEvent();
        eventPublisherBiz.triggerNotify(approvalPo);
        return R.data(data);
    }

    /**
     * 审批状态变更并返回目前审批模板对应的业务id
     *
     * @param approvalId
     *            审批id
     * @param approval
     *            审批参数
     * @return {@link R}<{@link Long}>
     */
    @ApiOperation("审批状态变更")
    @PostMapping("/{approvalId}/approval-change/next")
    public R<NotifyVo> approvalChangeAndReturnNextOne(@PathVariable Long approvalId, @RequestBody ApprovalDTO approval) throws UnsupportedEncodingException {
        ApprovalPo approvalPo = processBizService.calculateNextOne(approvalId, approval.getUseId(), approval);
        // trigger event.
        eventPublisherBiz.triggerEvent();
        eventPublisherBiz.triggerNotify(approvalPo);
        ApprovalTemplatePo templatePo = approvalTemplateService.getById(approvalPo.getApprovalTemplateId());
        return R.data(notifyBiz.getNextApproval(templatePo.getCode()));
    }

    /**
     * 审批撤回
     *
     * @param approvalId 审批id
     * @param userDTO 用户dto
     * @return {@link R}<{@link String}>
     */
    @ApiOperation("审批撤回")
    @PostMapping("/{approvalId}/revoke")
    public R<String> approvalRevoke(@PathVariable Long approvalId, @RequestBody UserDTO userDTO) {
        return R.data(processBizService.revokeApproval(approvalId, userDTO).toString());
    }

    /**
     * 审批驳回
     *
     * @param approvalId 审批id
     * @param rejected 参数
     * @return {@link R}<{@link Void}>
     */
    @ApiOperation("审批驳回")
    @PostMapping("/{approvalId}/rejected")
    public R<Void> approvalRejected(@PathVariable Long approvalId, @RequestBody ApprovalRejectedDTO rejected) {
        processBizService.rejectApproval(approvalId, rejected);
        return R.ok();
    }

    /**
     * 审批驳回
     * @param approvalId 审批id
     * @param rejected 参数
     * @return {@link R}<{@link Void}>
     */
    @ApiOperation("审批驳回")
    @PostMapping("/{approvalId}/rejected/next")
    public R<NotifyVo> approvalRejectedAndReturnNextOne(@PathVariable Long approvalId, @RequestBody ApprovalRejectedDTO rejected) {
        ApprovalPo approvalPo = processBizService.rejectApproval(approvalId, rejected);
        ApprovalTemplatePo templatePo = approvalTemplateService.getById(approvalPo.getApprovalTemplateId());
        return R.ok(notifyBiz.getNextApproval(templatePo.getCode()));
    }

    /**
     * 查询当前所有的审批节点
     *
     * @param approval 审批
     * @return {@link R}<{@link ProcessDetailActiveVO}>
     */
    @ApiOperation("查询当前所有的审批节点")
    @PostMapping("/nodes")
    public R<ProcessDetailActiveVO> getProcessDetailList(@RequestBody ApprovalMapDTO approval) {
        return R.data(processBizQuery.getProcessDetailList(approval));
    }

    /**
     * 根据审批实例ID列表查询审批进度
     *
     * @param approval 审批
     * @return {@link R}<{@link Map}<{@link Long}, {@link String}>>
     */
    @ApiOperation("根据审批实例ID列表查询审批进度")
    @PostMapping("/processing")
    public R<Map<Long, String>> mapApproval(@RequestBody ApprovalMapDTO approval) {
        return R.data(processBizQuery.mapApproval(approval.getApprovalIdList()));
    }

    /**
     * 查询全流程
     *
     * @param approval 审批
     * @return {@link R}<{@link List}<{@link List}<{@link EntireProcessDetailVo}>>>
     * @throws ExecutionException 执行异常
     * @throws InterruptedException 中断异常
     */
    @ApiOperation("查询全流程")
    @PostMapping("/all-nodes")
    public R<List<List<EntireProcessDetailVo>>> getAllProcessDetailList(@RequestBody ApprovalMapDTO approval)
        throws ExecutionException, InterruptedException {
        return R.data(processBizQuery.getAllProcessList(approval.getApprovalIdList()));
    }

    /**
     * 根据状态查询审批列表查询[后端服务用]
     *
     * @param project
     *            项目
     * @param approvalTemplateId
     *            审批模板id
     * @param userId
     *            用户id
     * @param pageNum
     *            页面num
     * @param pageSize
     *            页面大小
     * @return {@link R}<{@link List}<{@link ApprovalVo}>>
     */
    @ApiOperation("根据状态查询审批列表查询[后端服务用]")
    @GetMapping("/list")
    public R<List<ApprovalVo>> getInstanceStatusList(
        @RequestHeader(value = "projectName", required = false) String projectName,
        @RequestParam(value = "projectName", required = false) String project, String approvalTemplateId, Long userId,
        @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "20") Integer pageSize) {
        if (StringUtils.isEmpty(projectName)) {
            projectName = project;
        }
        return R
            .data(processBizQuery.getInstanceStatusList(projectName, approvalTemplateId, userId, pageNum, pageSize));
    }

    @ApiOperation("根据状态查询审批列表查询[后端服务用]")
    @PostMapping("/list")
    public R<List<ApprovalVo>> listInstanceStatusList(
            @RequestHeader(value = "projectName", required = false) String projectName,
            @RequestParam(value = "projectName", required = false) String project, @RequestBody ApprovalStatusDTO approvalStatus) {
        if (StringUtils.isEmpty(projectName)) {
            projectName = project;
        }
        return R.data(processBizQuery.listInstanceStatusList(projectName, approvalStatus.getApprovalTemplateId(),
                approvalStatus.getApprovalTemplateIdList(),
                        approvalStatus.getUserIdList(), approvalStatus.getPageNum(), approvalStatus.getPageSize()));
    }

    /**
     * 查询审批
     *
     * @param approvalTemplateCode
     *            审批模板Code
     * @return {@link R}<{@link Collection}<{@link ApprovalPersonVo}>>
     */
    @ApiOperation("查询审批")
    @GetMapping("/{approvalTemplateCode}/approvals")
    public R<Collection<ApprovalPersonVo>> getApprovals(@PathVariable String approvalTemplateCode) {
        return R.data(processDetailBizService.getApprovals(approvalTemplateCode));
    }

    /**
     * 查询审批模板中的审批人
     *
     * @param approval
     *            审批参数
     * @return {@link R}<{@link Collection}<{@link ApprovalPersonVo}>>
     */
    @ApiOperation("查询审批模板中的审批人")
    @PostMapping("/approvals")
    public R<Collection<ApprovalPersonVo>> listApprovals(@RequestBody ApprovalTemplateMapDTO approval) {
        return R.data(processDetailBizService.listApprovals(approval.getApprovalTemplateIdList()));
    }

    /**
     * 获得审批实例模板图
     *
     * @param approvalId
     *            审批实例id
     * @return {@link R}<{@link String}>
     */
    @ApiModelProperty("查询审批模板全流程")
    @GetMapping("/{approvalId}/template")
    public R<String> getApprovalTemplateDiagram(@PathVariable Long approvalId) {
        return R.data(processBizQuery.getApprovalTemplateDiagram(approvalId));
    }

    @PostMapping("/page")
    public R<Page<ApprovalVo>> pageApproval(@RequestBody ApprovalQueryDTO approvalQueryDTO) {
        return R.data(processBizService.pageApproval(approvalQueryDTO));
    }

    /**
     * 审批节点转让
     * @param dto
     * @return
     */
    @PostMapping("/transferNode")
    public R<Boolean> transferNode(@Validated @RequestBody ApprovalTransferNodeDTO dto) {
        return R.data(processBizService.transferNode(dto));
    }

    /**
     * 催办
     * @param approvalId 审批实例id
     * @param bizType 日志中心-业务类型
     * @return
     */
    @GetMapping("/urge/{approvalId}")
    public R<Boolean> urge(@PathVariable Long approvalId, @RequestParam(required = false) String bizType,
                           @RequestParam(required = false, defaultValue = "0") Integer voucherType,
                           @RequestHeader(name = "app_key", defaultValue = "") String appKey) {
        return R.data(processBizService.urge(approvalId, bizType, voucherType, "PaaS".equalsIgnoreCase(appKey)));
    }
}
